package main

import (
	"github.com/sirupsen/logrus"
	"gopkg.in/gemnasium/logrus-airbrake-hook.v2"
	"os"
	"github.com/spf13/cobra"
)
func init(){
	//打印调用的方法，这会增加打印的开销
	logrus.SetReportCaller(true)

	//如果不确定是否连接终端，但是想要保证日志输出格式一致，那么需要指定
	logrus.SetFormatter(&logrus.TextFormatter{
		DisableColors: true,
		FullTimestamp: true,
	})
	//如果需要打印彩色日志，需要指定
	logrus.SetFormatter(&logrus.TextFormatter{
		ForceColors: true,
		FullTimestamp: true,
	})
	//如果设置为TextFormatter，如果没有连接终端，那么输出和http://godoc.org/github.com/kr/logfmt兼容
	logrus.SetFormatter(&logrus.TextFormatter{})
	//如果设置为JSONFormatter，那么使用logstash或Splunk可以非常容易地解析日志
	logrus.SetFormatter(&logrus.JSONFormatter{})
	logrus.SetLevel(logrus.WarnLevel)
	logrus.SetOutput(os.Stdout)

	cobra.OnInitialize()
}

type Daemon struct{
	logger *logrus.Logger
	cmd *cobra.Command
	version bool
}
func (d *Daemon)Execute(){
	d.cmd.Execute()
}

//目标是从docker源码中学习golang daemon的构建技巧
func main(){
	//使用
	logrus.Info("test")
	logrus.WithFields(logrus.Fields{
		"animal":"walrus",
	}).Info("A walrus appears")

	contextLogger := logrus.WithFields(logrus.Fields{
		"common": "this is a common filed",
		"other": "I also should be logged always",
	})
	contextLogger.Info("I'll be logged with common and other field")
	contextLogger.Info("me too")

	//对于更高级的用法，你可以在一个应用中打印日志到不同的位置，你还可以创建一个logrus的Logger实例
	var logger1 = logrus.New()
	logger1.Out = os.Stdout
	logger1.SetOutput(os.Stdout)
	logger1.WithFields(logrus.Fields{
		"animal":"walrus",
		"size": 10,
	}).Info("test")

	//logrus鼓励通过日志记录字段而不是冗长且无法分析的错误消息进行结构化日志记录，而不是通过%d%s
	logrus.WithFields(logrus.Fields{
		"event": "event",
		"topic": "topic",
		"key": "key",
	}).Info("Failed to send event")

	str1 := "test1"
	str2 := "test2"
	logger2 := logrus.New()
	logger2.SetReportCaller(true)
	logger2.SetFormatter(&logrus.TextFormatter{
		ForceColors: true,
		DisableLevelTruncation: true,
		PadLevelText: true,
	})
	filedT := logger2.WithFields(logrus.Fields{
		"str1": str1,
		"str2": str2,
	})

	str1 = "test11"
	str2 = "test22"
	filedT.Info("the str has't changed")
	filedT.Warn("the str has't changed")

	//钩子函数，回调函数
	//你可以为不同级别的日志级别设置钩子函数
	logger2.SetFormatter(&logrus.TextFormatter{
		ForceColors: true,
	})
	logger2.AddHook(airbrake.NewHook(123, "xyz", "production"))
	logger2.Errorf("hook")
	logger2.Errorf("hooksss")

	daemon := &Daemon{}
	daemon.logger = logger2
	daemon.cmd = &cobra.Command{
		Use: "test",
		Short: "test short",
		Long: "test long details",
		//解析到主命令标志位结束为止
		TraverseChildren: true,
		PersistentPreRun: func(cmd *cobra.Command, args []string){
			logger2.Info("test")
			if(daemon.version){
				logger2.Info("version")
			}
			testFunc()
		},
	}
	flags := daemon.cmd.Flags()
	flags.BoolVarP(&daemon.version,"version", "v", false,"Print version information and quit")
	subCmd := &cobra.Command{
		Use: "test1",
		Short: "test1 short",
		Long: "test long details",
		Run: func(cmd *cobra.Command, args []string){
			logger2.Info("test1")
		},
	}
	var required bool
	daemon.cmd.AddCommand(subCmd)
	subCmd.Flags().BoolVarP(&required, "required", "r", false, "required")
	subCmd.MarkFlagRequired("required")
	var perF bool
	subCmd.PersistentFlags().BoolVarP(&perF, "perR", "p", false, "perRequired")
	subCmd.MarkPersistentFlagRequired("perR")

	//自定义参数
	//可以构建如下的验证器
	//- NoArgs	如果输入参数就会报错
	//- ArbitraryArgs	可以接收任何参数
	//- MinimumNArgs	至少
	daemon.Execute()
}
